﻿/*
   Copyright 2012 University of Southampton

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.IO;
using System.ServiceModel.Web;
using System.Configuration;
using System.Web.Configuration;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.Web;
using uk.ac.soton.ses.DAL;


namespace uk.ac.soton.ses
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class EP2DCService : EP2DCDataTypes.IEP2DCService
    {

        public string HelloWorld()
        {
            return String.Format("This is the EP2DC service. Time is {0}.", DateTime.Now.ToString());
        }

        public EP2DCDataTypes.MDCIdentifierMessage CreateContainer(string userToken)
        {
            EP2DCDataTypes.MDCIdentifierMessage res = new EP2DCDataTypes.MDCIdentifierMessage();

            try
            {
                EP2DCDataTypes.MDCid result = HDCFileAccess.CreateContainer(userToken);
                res.MDCIds.Add(result.MDCIDString);
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }

            return res;
        }

        public EP2DCDataTypes.MDCIdentifierMessage GetMDCIDsInContainer(string userToken, string MDCcontainerID)
        {
            EP2DCDataTypes.MDCIdentifierMessage resultMsg = new EP2DCDataTypes.MDCIdentifierMessage();
            try
            {
                List<EP2DCDataTypes.MDCid> result = HDCFileAccess.GetMDCIDsInContainer(userToken, new EP2DCDataTypes.MDCid() { MDCIDString = MDCcontainerID });

                //convert

                foreach (EP2DCDataTypes.MDCid curDoi in result)
                {
                    resultMsg.MDCIds.Add(curDoi.MDCIDString);
                }
            }
            catch (FileNotFoundException e)
            {
                resultMsg.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.NotFound;
                resultMsg.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            return resultMsg;
        }

        public EP2DCDataTypes.MDCIdentifierMessage AddUriToContainer(string userToken, string MDCcontainerID, string uri)
        {
            EP2DCDataTypes.MDCIdentifierMessage res = new EP2DCDataTypes.MDCIdentifierMessage();
            try
            {
                EP2DCDataTypes.MDCid result = HDCFileAccess.AddUriToContainer(userToken, MDCcontainerID, new Uri(uri));

                res.MDCIds.Add(result.MDCIDString);
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            return res;
        }

        public EP2DCDataTypes.MDCIdentifierMessage AddMDCIDToContainer(string userToken, string MDCcontainerID, string mdcid)
        {
            EP2DCDataTypes.MDCIdentifierMessage res = new EP2DCDataTypes.MDCIdentifierMessage();

            try
            {
                EP2DCDataTypes.MDCid containerID = new EP2DCDataTypes.MDCid() { MDCIDString = MDCcontainerID };
                EP2DCDataTypes.MDCid fileID = new EP2DCDataTypes.MDCid() { MDCIDString = mdcid };

                EP2DCDataTypes.MDCid result = HDCFileAccess.AddMDCIdToContainer(userToken, containerID, fileID);
                
                res.MDCIds.Add(result.MDCIDString);
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            return res;
        }

        public EP2DCDataTypes.MDCIdentifierMessage UploadFile(string userToken, string MDCcontainerID, Stream fileStream, string fileName, long length, bool validateXML)
        {
            EP2DCDataTypes.MDCIdentifierMessage res = new EP2DCDataTypes.MDCIdentifierMessage();
            using (StreamWriter log = new StreamWriter(@"C:\temp\uploaddebug.log",true))
            {
                try
                {
                    //EPrints plugin doesn't send the right data for HttpContext to work, so we'll process the stream manually if necessary
                    if (HttpContext.Current.Request.Files.Count > 0)
                    {
                        log.WriteLine("Receiving file from HttpContext.");
                        for (int i = 0; i < HttpContext.Current.Request.Files.Count; i++)
                        //foreach (HttpPostedFile incomingFile in HttpContext.Current.Request.Files)
                        {
                            HttpPostedFile incomingFile = HttpContext.Current.Request.Files[i];
                            EP2DCDataTypes.MDCid result = HDCFileAccess.UploadStream(userToken, incomingFile.FileName, incomingFile.InputStream, MDCcontainerID, validateXML);
                            res.MDCIds.Add(result.MDCIDString);
                        }
                    }
                    //Assume we have a stream because checking its length is not supported
                    else
                    {
                        log.WriteLine("Receiving file from stream.");
                        EP2DCDataTypes.MDCid result = HDCFileAccess.UploadStream(userToken, fileName, fileStream, MDCcontainerID, validateXML);
                        res.MDCIds.Add(result.MDCIDString);
                    }
                }
                catch (EP2DCDataTypes.XmlValidatorException e)
                {
                    res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
                }
                catch (Exception e)
                {
                    OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                    response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                    res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
                }
                if (res.errorMessage != null)
                {
                    log.WriteLine("Error message was:" + res.errorMessage);
                }
                log.Flush();
            }

            return res;
        }

        public DateTime GetServerTime()
        {
            return DateTime.Now;
        }

        public EP2DCDataTypes.URIMsg GetURIForMDCID(string userToken, string MDCID)
        {

            EP2DCDataTypes.URIMsg res = new EP2DCDataTypes.URIMsg();
            try
            {
                EP2DCDataTypes.MDCUri result = HDCFileAccess.GetURIForMDCid(new EP2DCDataTypes.MDCid() { MDCIDString = MDCID });
                res.displayText = result.displayText;
                res.uri = result.uri;
            }
            catch (FileNotFoundException e)
            {
                res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            return res;
        }

        public EP2DCDataTypes.MDCHTMLMessage GetHTMLForMDCID(string userToken, string MDCID)
        {
            EP2DCDataTypes.MDCHTMLMessage returnMessage = new EP2DCDataTypes.MDCHTMLMessage();

            try
            {
                int intFileID = -1;
                if (int.TryParse(MDCID, out intFileID))
                {
                    returnMessage.Html = HDCFileAccess.GetHTMLForMDCid(intFileID);
                }
            }
            catch (FileNotFoundException e)
            {
                returnMessage.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                returnMessage.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }

            return returnMessage;
        }

        public EP2DCDataTypes.MDCIdentifierMessage GetMDCIDForObjectPath(string userToken, string objectPath)
        {
            EP2DCDataTypes.MDCIdentifierMessage returnObject = new EP2DCDataTypes.MDCIdentifierMessage();
            try
            {
                EP2DCDataTypes.MDCid result = HDCFileAccess.GetMDCIDForObjectPath(userToken, objectPath);
                returnObject.MDCIds.Add(result.MDCIDString);

            }
            catch (FileNotFoundException e)
            {
                returnObject.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                returnObject.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }
            return returnObject;
        }


        //TODO:Decide what to do about DeleteContainer
        public EP2DCDataTypes.ACKMsg DeleteContainer(string userToken, string MDCcontainerID)
        {
            EP2DCDataTypes.ACKMsg responseMsg = new EP2DCDataTypes.ACKMsg();
            try
            {
                bool result = HDCFileAccess.DeleteContainer(userToken, MDCcontainerID);
                responseMsg.isSuccessful = result;

            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                responseMsg.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
     
            }
            return responseMsg;
        }

        //TODO:Decide what to do about ListDataTypes
        public EP2DCDataTypes.DataTypeMsg ListDataTypes(string userToken)
        {
            EP2DCDataTypes.DataTypeMsg res = new EP2DCDataTypes.DataTypeMsg();
            try
            {
                List<EP2DCDataTypes.DataTypeDescriptor> dataTypes = HDCFileAccess.ListDataTypes(userToken);

                //convert
                foreach (EP2DCDataTypes.DataTypeDescriptor curType in dataTypes)
                {
                    res.DataTypes.Add(new EP2DCDataTypes.DataTypeMember() { Id = curType.Id, DisplayText = curType.DisplayText });
                }
            }
            catch (Exception e)
            {
                OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
                response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                res.errorMessage = new EP2DCDataTypes.MDCErrorMessage() { displayErrorMsg = e.Message, fullError = e.StackTrace };
            }

            return res;
        }

    }
}
